<?php

namespace controller\admin;

defined('IA_ROOT') || exit();

use facade\Model;
use facade\View;
use facade\Util;

// 页面管理
class Page extends Base
{
    // 列表
    public function index()
    {
        if (Util::isAjax()) {
            $param = Util::param();
            $start = ($param['page'] - 1) * $param['limit'];
            $limit = $param['limit'];
            $where = "";

            // 搜索
            if (!empty($param['search'])) {
                foreach ((array)$param['search'] as $k => $v) {
                    if (strlen($v)) {
                        if (in_array($k, ['is_full', 'is_nav', 'status'])) {
                            $where .= " AND `$k` = '$v'";
                        } else if (in_array($k, ['start', 'end'])) {
                            $timestamp = strtotime($v);
                            if ($k == 'start')
                                $where .= " AND `time` >= '$timestamp'";
                            else
                                $where .= " AND `time` <= '$timestamp'";
                        } else {
                            $where .= " AND `$k` like '%{$v}%'";
                        }
                    }
                }
            }

            // 数据库查询
            $count = Model::fetchColumn("SELECT COUNT(*) FROM `page` WHERE 1=1 $where AND `pid` = 0 ORDER BY `id` ASC, `sort` DESC");
            $data = Model::fetchAll("SELECT * FROM `page` WHERE 1=1 $where AND `pid` = 0 ORDER BY `id` ASC, `sort` DESC LIMIT $start, $limit");
            $ids = array_map(function ($item) {
                return $item['id'];
            }, $data);
            $idStr = implode(',', $ids);
            if ($idStr) {
                $childs = Model::fetchAll("SELECT * FROM `page` WHERE 1=1 $where AND `pid` IN ($idStr) ORDER BY `id` ASC, `sort` DESC");
                $data = array_merge($data, $childs);
            }
            $data = $this->format_tree($data, 'title');

            // 分页输出
            if ($count) {
                $res['code'] = 0;
            } else {
                $res['code'] = 1;
                $res['msg'] = '暂无记录';
            }
            $res['count'] = $count;
            $res['data'] = array_map(function ($item) {
                if (preg_match('#(/static/upload/[^\s"\'<>]+?\.[^\s"\'<>]+)#i', $item['cover'], $match)) {
                    $item['cover'] = $this->site_url . $match[1];
                }
                if (!$item['cover'] && preg_match_all('#<img[^>]*src=(["\'])(.*?)(/static/upload/[^\s"\'<>]+?\.[^\s"\'<>]+)\1#i', $item['content'], $matches, PREG_SET_ORDER)) {
                    $item['cover'] = $this->site_url . $matches[0][3];
                }
                $item['time'] = date('Y-m-d H:i', $item['time']);
                return $item;
            }, $data);
            exit(json_encode($res));
        }
        View::display('admin/page/index.html');
    }

    // 创建
    public function create()
    {
        $pid = (int)Util::param('id');
        $rows = Model::fetchAll("SELECT * FROM `page` ORDER BY `sort` DESC, `id` ASC");
        View::assign(['pid' => $pid, 'page' => $this->format_tree($rows, 'title')]);
        View::display('admin/page/create.html');
    }

    // 保存
    public function save()
    {
        $param = Util::param(['title', 'pid', 'slug', 'content', 'description', 'cover', 'sort', 'seo_title', 'seo_description', 'is_full', 'is_nav', 'status']);
        empty($param['title']) && Util::errMsg('标题不能为空');

        // 重复验证
        $check = Model::fetchColumn("SELECT `title` FROM `page` WHERE `title`=:title ORDER BY `id`", [':title' => $param['title']]);
        $check && Util::errMsg('标题重名');
        if (!empty($param['slug'])) {
            $param['slug'] = preg_replace('/[\W]/', ' ', $param['slug']);
            $param['slug'] = preg_replace('/\s+/', ' ', $param['slug']);
            $param['slug'] = strtolower($param['slug']);
            $param['slug'] = str_replace(' ', '-', $param['slug']);
            !preg_match('#^[a-z0-9_-]{2,100}$#i', $param['slug']) && Util::errMsg('别名只能2~100位英文字母数字下划线中划线');
            $check = Model::fetchColumn("SELECT `slug` FROM `page` WHERE `slug`=:slug ORDER BY `id`", [':slug' => $param['slug']]);
            $check && Util::errMsg('别名重复');
        }

        if (!empty($param['cover'])) {
            !preg_match('/\.(gif|jpe?g|png|bmp|webp|psd|svg|tiff)$/i', $param['cover']) && Util::errMsg('图片格式错误');
            if (preg_match('#(/static/upload/[^\s"\'<>]+?\.[^\s"\'<>]+)#i', $param['cover'], $match)) {
                $param['cover'] = $match[1];
            }
        }

        // 写入数据库记录日志
        $param['time'] = time();
        if (preg_match_all('#<[^>]*=(["\'])(.*?)(/static/(res|upload)/[^\s"\'<>]+?\.[^\s"\'<>]+)\1#i', $param['content'], $matches, PREG_SET_ORDER)) {
            foreach ($matches as $match) {
                $param['content'] = str_replace($match[2] . $match[3], $match[3], $param['content']);
            }
        }
        $lastInsertId = Model::insert('page', $param);
        if ($lastInsertId) {
            // 修改媒体状态
            $paths = [0 => [], 2 => []];
            if (preg_match('#(/static/upload/[^\s"\'<>]+?\.[^\s"\'<>]+)#i', $param['cover'], $match)) {
                if (is_file(IA_ROOT . $match[1]))
                    $paths[0][] = $match[1];
                else
                    $paths[2][] = $match[1];
            }
            if (preg_match_all('#<[^>]*=(["\'])(.*?)(/static/upload/[^\s"\'<>]+?\.[^\s"\'<>]+)\1#i', $param['content'], $matches, PREG_SET_ORDER)) {
                foreach ($matches as $match) {            
                    if (is_file(IA_ROOT . $match[3]))
                        $paths[0][] = $match[3];
                    else
                        $paths[2][] = $match[3];
                }
            }
            $paths[0] && Model::update('media', ['status' => 0], ['path' => $paths[0]]);
            $paths[2] && Model::update('media', ['status' => 2], ['path' => $paths[2]]);
            $this->log('创建页面', "创建页面 {$param['title']} 成功", 0);
            Util::errMsg(['code' => 0, 'msg' => '创建页面成功', 'url' => Util::url('/admin/page/index.html')]);
        } else {
            $this->log('创建页面', "创建页面 {$param['title']} 失败", 1);
            Util::errMsg(['code' => 1, 'msg' => '创建页面失败']);
        }
    }

    // 编辑
    public function edit($id = 0)
    {
        $row = Model::fetch("SELECT * FROM `page` WHERE `id`=:id", [':id' => $id]);
        !$row && Util::errMsg('ID错误');
        if (preg_match('#(/static/upload/[^\s"\'<>]+?\.[^\s"\'<>]+)#i', $row['cover'], $match)) {
            $row['cover'] = $this->subdir . $match[1];
        }
        if (preg_match_all('#<[^>]*=(["\'])(.*?)(/static/(res|upload)/[^\s"\'<>]+?\.[^\s"\'<>]+)\1#i', $row['content'], $matches, PREG_SET_ORDER)) {
            foreach ($matches as $match) {
                $row['content'] = str_replace($match[2] . $match[3], $this->subdir . $match[3], $row['content']);
            }
        }
        $rows = Model::fetchAll("SELECT * FROM `page` ORDER BY `sort` DESC, `id` ASC");
        View::assign(['row' => $row, 'page' => $this->format_tree($rows, 'title')]);
        View::display('admin/page/edit.html');
    }

    // 更新
    public function update()
    {
        $param = Util::param(['id', 'title', 'pid', 'slug', 'content', 'description', 'cover', 'sort', 'seo_title', 'seo_description', 'is_full', 'is_nav', 'status']);
        empty($param['title']) && Util::errMsg('标题不能为空');
        $row = Model::fetch("SELECT * FROM `page` WHERE `id`=:id", [':id' => $param['id']]);
        !$row && Util::errMsg('ID错误');

        // 重复验证
        $check = Model::fetchColumn("SELECT `title` FROM `page` WHERE `title`=:title ORDER BY `id`", [':title' => $param['title']]);
        $check && $check !== $row['title'] && Util::errMsg('标题重名');
        if (!empty($param['slug'])) {
            $param['slug'] = preg_replace('/[\W]/', ' ', $param['slug']);
            $param['slug'] = preg_replace('/\s+/', ' ', $param['slug']);
            $param['slug'] = strtolower($param['slug']);
            $param['slug'] = str_replace(' ', '-', $param['slug']);
            !preg_match('#^[a-z0-9_-]{2,100}$#i', $param['slug']) && Util::errMsg('别名只能2~100位英文字母数字下划线中划线');
            $check = Model::fetchColumn("SELECT `slug` FROM `page` WHERE `slug`=:slug ORDER BY `id`", [':slug' => $param['slug']]);
            $check && $check !== $row['slug'] && Util::errMsg('别名重复');
        }

        if (!empty($param['cover'])) {
            !preg_match('/\.(gif|jpe?g|png|bmp|webp|psd|svg|tiff)$/i', $param['cover']) && Util::errMsg('图片格式错误');
            if (preg_match('#(/static/upload/[^\s"\'<>]+?\.[^\s"\'<>]+)#i', $param['cover'], $match)) {
                $param['cover'] = $match[1];
            }
        }

        // 更新数据库记录日志
        if (preg_match_all('#<[^>]*=(["\'])(.*?)(/static/(res|upload)/[^\s"\'<>]+?\.[^\s"\'<>]+)\1#i', $param['content'], $matches, PREG_SET_ORDER)) {
            foreach ($matches as $match) {
                $param['content'] = str_replace($match[2] . $match[3], $match[3], $param['content']);
            }
        }
        $rowCount = Model::update('page', $param, ['id' => $param['id']]);

        // 修改媒体状态
        $paths = [0 => [], 1 => [], 2 => []];
        if (preg_match('#(/static/upload/[^\s"\'<>]+?\.[^\s"\'<>]+)#i', $row['cover'], $match)) {
            if (is_file(IA_ROOT . $match[1]))
                $paths[1][] =  $match[1];
            else
                $paths[2][] =  $match[1];
        }
        if (preg_match('#(/static/upload/[^\s"\'<>]+?\.[^\s"\'<>]+)#i', $param['cover'], $match)) {
            if (is_file(IA_ROOT .  $match[1]))
                $paths[0][] =  $match[1];
            else
                $paths[2][] =  $match[1];
        }
        if (preg_match_all('#<[^>]*=(["\'])(.*?)(/static/upload/[^\s"\'<>]+?\.[^\s"\'<>]+)\1#i', $row['content'], $matches, PREG_SET_ORDER)) {
            foreach ($matches as $match) {
                if (is_file(IA_ROOT . $match[3]))
                    $paths[1][] = $match[3];
                else
                    $paths[2][] = $match[3];
            }
        }
        if (preg_match_all('#<[^>]*=(["\'])(.*?)(/static/upload/[^\s"\'<>]+?\.[^\s"\'<>]+)\1#i', $param['content'], $matches, PREG_SET_ORDER)) {
            foreach ($matches as $match) {
                if (is_file(IA_ROOT . $match[3]))
                    $paths[0][] = $match[3];
                else
                    $paths[2][] = $match[3];
            }
        }
        $paths[1] && Model::update('media', ['status' => 1], ['path' => array_unique($paths[1])]);
        $paths[0] && Model::update('media', ['status' => 0], ['path' => array_unique($paths[0])]);
        $paths[2] && Model::update('media', ['status' => 2], ['path' => array_unique($paths[2])]);
        if ($rowCount) {
            // 删除缓存
            $this->clearCache($param['id']);
            $this->log('编辑页面', "编辑页面 {$row['title']} -> {$param['title']} 成功", 0);
            Util::errMsg(['code' => 0, 'msg' => '编辑页面成功', 'url' => Util::url('/admin/page/index.html')]);
        } else {
            $this->log('编辑页面', "没有改变 {$row['title']} 信息", 0);
            Util::errMsg(['code' => 1, 'msg' => '没有改变信息']);
        }
    }

    // 修改属性
    public function modify()
    {
        $param = Util::param(['id', 'field', 'value']);
        empty($param['id']) && Util::errMsg('ID错误');
        $row = Model::fetch("SELECT * FROM `page` WHERE `id`=:id", [':id' => $param['id']]);
        !$row && Util::errMsg('ID非法');
        (empty($param['field']) || !in_array($param['field'], ['title', 'slug', 'description', 'sort', 'is_full', 'is_nav', 'status'])) && Util::errMsg('非法字段');

        // 验证字段
        if ($param['field'] == 'title') {
            empty($param['value']) && Util::errMsg('标题不能为空');
            $check = Model::fetchColumn("SELECT `title` FROM `page` WHERE `title`=:title ORDER BY `id`", [':title' => $param['value']]);
            $check && $check !== $row['title'] && Util::errMsg('标题重名');
        }
        if ($param['field'] == 'slug') {
            !preg_match('#^[a-z0-9_-]{2,100}$#i', $param['value']) && Util::errMsg('别名只能2~100位英文字母数字下划线中划线');
            $check = Model::fetchColumn("SELECT `slug` FROM `page` WHERE `slug`=:slug ORDER BY `id`", [':slug' => $param['value']]);
            $check && $check !== $row['slug'] && Util::errMsg('别名重复');
        }
        if (in_array($param['field'], ['is_full', 'is_nav', 'status'])) {
            !is_numeric($param['value']) && Util::errMsg('填写整数');
        }

        // 更新数据库记录日志
        $rowCount = Model::update('page', [$param['field'] => $param['value']], ['id' => $param['id']]);
        if ($rowCount) {
            // 删除缓存
            $this->clearCache($param['id']);
            $this->log('修改属性', "修改属性 {$param['field']}: {$row[$param['field']]} -> {$param['value']} 成功", 0);
            Util::errMsg(['code' => 0, 'msg' => '修改成功']);
        } else {
            $this->log('修改属性', "修改属性 {$param['field']}: {$row[$param['field']]} -> {$param['value']} 失败", 1);
            Util::errMsg(['code' => 1, 'msg' => '修改失败']);
        }
    }

    // 软删除
    public function delete()
    {
        $param = Util::param(['id']);
        (empty($param) || !isset($param['id'])) && Util::errMsg('请选择数据');

        // 如果有子页面
        $idStr = implode(',', (array)$param['id']);
        $check = Model::fetchColumn("SELECT `id` FROM `page` WHERE `pid` IN ($idStr)");
        $check && Util::errMsg('请先删除子页面');

        $idStr = implode(',', (array)$param['id']);
        $rows = Model::fetchAll("SELECT `title`, `content` FROM `page` WHERE `id` IN ($idStr)");
        $names = [];
        $paths = [1 => [], 2 => []];
        foreach ($rows as $row) {
            $names[] = $row['title'];
            if (preg_match_all('#<[^>]*=(["\'])(.*?)(/static/upload/[^\s"\'<>]+?\.[^\s"\'<>]+)\1#i', $row['content'], $matches, PREG_SET_ORDER)) {
                foreach ($matches as $match) {
                    if (is_file(IA_ROOT . $match[3]))
                        $paths[1][] = $match[3];
                    else
                        $paths[2][] = $match[3];
                }
            }
        }

        // 软删除数据记录日志
        $rowCount = Model::delete('page', ['id' => $param['id']]);
        if ($rowCount) {
            // 删除缓存
            $this->clearCache($param['id']);
            // 修改媒体状态
            $paths[1] && Model::update('media', ['status' => 1], ['path' => array_unique($paths[1])]);
            $paths[2] && Model::update('media', ['status' => 2], ['path' => array_unique($paths[2])]);
            $this->log('删除页面', "删除页面 " . implode(' ', $names) . " 成功", 0);
            Util::errMsg(['code' => 0, 'msg' => '删除成功']);
        } else {
            $this->log('删除页面', "删除页面 " . implode(' ', $names) . " 失败", 1);
            Util::errMsg(['code' => 1, 'msg' => '删除失败']);
        }
    }

    // 删除缓存
    private function clearCache($ids = 0)
    {
        if ($ids) {
            $ids = (array)$ids;
            $ids = array_unique($ids);
            $idStr = implode(',', $ids);
            $rows = Model::fetchAll("SELECT `id`, `slug` FROM `page` WHERE `id` IN ($idStr)");
            $prefix = $this->site_url . "/";
            foreach ($rows as $row) {
                $file_name = md5($prefix);
                $cache_file = IA_ROOT . '/mvc/tpl/' . substr($file_name, 0, 2) . '/' . $file_name . '.php';
                if (file_exists($cache_file))
                    unlink($cache_file);
                $file_name = md5('/page/' . ($row['slug'] ? $row['slug'] : $row['id']) . '.html');
                $cache_file = IA_ROOT . '/mvc/tpl/' . substr($file_name, 0, 2) . '/' . $file_name . '.php';
                if (file_exists($cache_file))
                    unlink($cache_file);
                // 删除分页缓存
                $count = Model::fetchColumn("SELECT COUNT(*) FROM `page` WHERE `pid`=:pid AND `status`=0 ORDER BY `id` DESC", [':pid' => $row['id']]);
                for ($i = 2; $i <= ceil($count / 10); $i++) {
                    $file_name = md5($prefix . 'page/' . ($row['slug'] ? $row['slug'] : $row['id']) . '/page-' . $i . '.html');
                    $cache_file = IA_ROOT . '/mvc/tpl/' . substr($file_name, 0, 2) . '/' . $file_name . '.php';
                    file_exists($cache_file) && unlink($cache_file);
                }
            }
        }
    }
}
